<template>
  <common-page
    :title="`${isEdit ? '编辑组件' : '新增组件'}（所属分类：${typeName}）`"
  >
    <div slot="header-content" class="header-edit-name">
      <span class="line">|</span>
      <span class="label">组件名称</span>
      <common-input
        v-model="form.name"
        placeholder="请输入组件名称"
        :maxlength="16"
        clearable
      ></common-input>
    </div>
    <el-button slot="header" @click="back()">返回</el-button>
    <el-button
      slot="header"
      type="primary"
      @click="persistence"
      :loading="isPersistenceLoading"
      >保存</el-button
    >
    <div
      class="screen-container"
      @click="clearPageStatus"
      slot="content"
      v-loading="isPageDataLoading"
    >
      <!-- 左边部分 -->
      <div class="left-config-wrap">
        <!-- 数据集标题 -->
        <div class="data-set-wrap">
          <div class="title">
            <common-marquee-text :content="datasetName"></common-marquee-text>
          </div>
          <div class="tool" @click="chooseDataSet">
            <svg aria-hidden="true" class="icon">
              <use xlink:href="#icon-tuominziyuan"></use>
            </svg>
            <!--            <i class="iconfont icon-shandian"></i>-->
          </div>
        </div>
        <common-input
          v-model="searchField"
          prefix-icon="el-icon-search"
        ></common-input>
        <!-- 字段列表 -->
        <div class="field-list-wrap" ref="fieldContainer">
          <!-- 维度字段列表 -->
          <div
            class="field-group-list-wrap"
            :style="{ height: fieldHeight + 'px' }"
          >
            <div class="field-group-title">维度</div>
            <div class="field-list">
              <div
                class="field-item-wrap"
                v-for="dimension in dimensionList"
                :key="dimension.fieldName"
                @mousedown="fieldMousedown($event, dimension, 'start')"
                @mouseup="fieldMouseup"
              >
                <svg class="icon" aria-hidden="true">
                  <use
                    :xlink:href="`#icon-${dimension.fieldType}-field-type`"
                  ></use>
                </svg>
                <common-marquee-text :content="dimension.fieldDescribe" />
              </div>
            </div>
          </div>
          <!-- 控制按钮 -->
          <div class="field-control">
            <div
              class="control-button"
              @mousedown="dragMousedown"
              @mouseup="dragMouseup"
            >
              <i class="iconfont icon-control"></i>
            </div>
          </div>
          <!-- 指标字段列表 -->
          <div
            class="field-group-list-wrap"
            :style="{ height: `calc(100% - ${fieldHeight}px - 16px)` }"
          >
            <div class="field-group-title">指标</div>
            <div class="field-list">
              <div
                class="field-item-wrap"
                v-for="indicators in indicatorsList"
                :key="indicators.fieldName"
                @mousedown="fieldMousedown($event, indicators, 'start')"
                @mouseup="fieldMouseup"
              >
                <svg class="icon" aria-hidden="true">
                  <use
                    :xlink:href="`#icon-${indicators.fieldType}-field-type`"
                  ></use>
                </svg>
                <common-marquee-text :content="indicators.fieldDescribe" />
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 右边部分 -->
      <div class="right-config-wrap">
        <!-- 顶部字段配置项 -->
        <div class="field-config-container-wrap">
          <div
            v-for="item in fieldContainerList"
            :key="item.key"
            class="field-config-container"
            :style="{ width: item.width }"
          >
            <div class="config-title">{{ item.label }}</div>
            <div
              class="field-content"
              :ref="item.key"
              :key="item.key"
              :style="{ borderColor: item.isPut ? item.color : 'transparent' }"
            >
              <common-marquee-text
                v-if="dataPoolField[item.key].length === 0"
                :is-auto-play="true"
                color="#999"
                :offset-duration="5"
                :content="item.description"
              />
              <!--              <span  class="field-description">{{ item.description }}</span>-->

              <field-config-container v-else :list="dataPoolField[item.key]">
                <div
                  v-for="field in dataPoolField[item.key]"
                  :key="field.key"
                  :class="[
                    'common-field-container',
                    'config-field',
                    `type-${field.fieldType}`,
                  ]"
                  @mousedown="fieldMousedown($event, field, 'end')"
                  @mouseup="fieldMouseup"
                >
                  <div class="config-field-inside">
                    <common-marquee-text :content="field.fieldDescribe" />
                    <i
                      class="el-icon-delete"
                      @mousedown.stop="deleteConfigField(item.key, field)"
                    ></i>
                  </div>
                </div>
              </field-config-container>
            </div>
          </div>
        </div>

        <div class="tools-control-wrap">
          <el-popover
            popper-class="chart-type-list-popover"
            placement="bottom"
            width="150"
            v-model="isChartType"
            trigger="click"
          >
            <icon-button
              slot="reference"
              icon="icon-chart-type"
              content="图表类型"
            ></icon-button>
            <div
              class="chart-type-list-container"
              :style="{ '--theme-color': systemInfo.theme }"
            >
              <div class="chart-group-title">图表选择</div>
              <div class="chart-type-list-wrap">
                <div
                  v-for="ct in chartTypeList"
                  :key="ct.getInfo().type"
                  @click="chartTypeChange(ct)"
                  @mouseover="chartTypeMouseover(ct)"
                  @mouseleave="chartTypeMouseleave(ct)"
                  :class="[
                    'chart-type-item-wrap',
                    ct.getInfo().type === form.chartType ? 'checked' : '',
                  ]"
                >
                  <svg class="icon" aria-hidden="true">
                    <use :xlink:href="`#icon-${ct.getInfo().icon}`"></use>
                  </svg>
                </div>
              </div>

              <template v-if="currentHoverChartType">
                <div class="chart-group-title">
                  {{ currentHoverChartType.getInfo().name }}
                </div>
                <div
                  class="chart-field-info"
                  v-for="dataPoolConfig in currentHoverChartDataPoolConfig"
                  :key="dataPoolConfig.key"
                  v-if="dataPoolConfig.limit !== 0"
                >
                  <div class="tag">
                    <span v-if="dataPoolConfig.limit > 0"
                      >{{ dataPoolConfig.limit }}个</span
                    >
                    <span v-if="dataPoolConfig.limit < 0">多个</span>
                  </div>
                  {{ dataPoolConfig.label }}
                </div>
              </template>

              <template v-if="currentChartType && !currentHoverChartType">
                <div class="chart-group-title">
                  {{ currentChartType.getInfo().name }}
                </div>
                <div
                  class="chart-field-info"
                  v-for="dataPoolConfig in currentDataPoolConfig"
                  :key="dataPoolConfig.key"
                  v-if="dataPoolConfig.limit !== 0"
                >
                  <div class="tag">
                    <span v-if="dataPoolConfig.limit > 0"
                      >{{ dataPoolConfig.limit }}个</span
                    >
                    <span v-if="dataPoolConfig.limit < 0">多个</span>
                  </div>
                  {{ dataPoolConfig.label }}
                </div>
              </template>
            </div>
          </el-popover>
          <icon-button
            v-if="classType !== 1"
            icon="icon-relation"
            content="关联配置"
            @click="handleRelation"
          >
          </icon-button>
          <icon-button
            v-if="currentGraph === 'e-chart'"
            icon="icon-chart-theme"
            content="图表颜色"
            @click="handleTheme"
          >
          </icon-button>
          <icon-button
            v-if="styleOptionConfig.length"
            icon="icon-chart-style"
            content="图表样式"
            @click.stop="showOptionDrawer"
          ></icon-button>
          <el-popover
            popper-class="chart-type-list-popover"
            placement="bottom"
            width="150"
            v-model="isRefresh"
            trigger="hover"
          >
            <icon-button
              slot="reference"
              icon="icon-renwu"
              :content="`刷新频率(${refreshLabel})`"
            ></icon-button>
            <div class="refresh-rate-wrap">
              <div
                class="refresh-rate-item"
                v-for="item in refreshRateList"
                :key="item.value"
                @click="refreshRateChange(item)"
              >
                {{ item.label }}
              </div>
            </div>
          </el-popover>
          <icon-button
            icon="icon-analysis"
            content="维度分析"
            @click="handleAnalysis"
          ></icon-button>
        </div>
        <div class="chart-preview-wrap">
          <div class="chart-preview-container">
            <!--            <base-chart :option="option"></base-chart>-->
            <common-graph
              v-if="currentGraph && currentConfigFieldLength"
              :graph="currentGraph"
              :option="option"
              :config="config"
            ></common-graph>
          </div>

          <common-drawer
            v-if="currentChartType"
            :title="`${currentChartType.getInfo().name} - 样式配置`"
            :visible.sync="isOptionDrawer"
          >
            <form-designer
              v-if="isOptionDrawer"
              :configs="styleOptionConfig"
              label-width="90px"
              @change="styleOptionConfigChange"
            ></form-designer>
          </common-drawer>
        </div>
      </div>

      <div
        v-show="dragField.status"
        @mouseup="dragFieldMouseup"
        :class="[
          'common-field-container',
          'drag-field',
          `type-${dragField.fieldType}`,
        ]"
        :style="{ left: `${dragField.left}px`, top: `${dragField.top}px` }"
      >
        <div class="drag-field-inside">
          {{ dragField.fieldDescribe }}
        </div>
      </div>
    </div>

    <data-set-dialog
      ref="dataset"
      :value="form.datasetId"
      @change="datasetChange"
      :datasetName="datasetName"
    ></data-set-dialog>
    <analysis-dialog
      ref="analysis"
      :value="form.analysis"
      @change="analysisChange"
    ></analysis-dialog>
    <theme-dialog
      ref="theme"
      :color="form.theme"
      @change="themeChange"
    ></theme-dialog>
    <relation-dialog
      ref="relation"
      :relation="relationConfig"
      :id="id"
      :fieldList="allDataPoolFieldList"
      :currentChart="currentChartType"
      @change="relationChange"
    ></relation-dialog>

    <common-edit-dialog
      :visible="isEditDialog"
      title="保存"
      :button-loading="isPersistenceLoading"
      @cancel="isEditDialog = false"
      @submit="persistence"
    >
      <el-form
        :model="form"
        :rules="rules"
        ref="form"
        label-width="60px"
        @submit.native.prevent
      >
        <el-form-item label="名称" prop="name">
          <common-input v-model="form.name" :maxlength="16"></common-input>
        </el-form-item>

        <common-add-dept
          ref="commonAddDept"
          :deptListParams="departmentList"
          @getCheckedDeptId="getCheckedDeptId"
          :deptId="form.deptId"
        ></common-add-dept>

        <el-form-item label="描述">
          <common-input
            v-model="form.description"
            type="textarea"
          ></common-input>
        </el-form-item>
      </el-form>
    </common-edit-dialog>
  </common-page>
</template>

<script>
import BaseChart from "@/components/EChart/components/BaseChart";
import CommonDrawer from "@/components/CommonDrawer";
import IconButton from "./components/IconButton";
import DataSetDialog from "./components/DataSetDialog";
import AnalysisDialog from "./components/AnalysisDialog";
import ThemeDialog from "./components/ThemeDialog";
import RelationDialog from "./components/RelationDialog";
import FieldConfigContainer from "./components/FieldConfigContainer";

import FormDesigner from "@/components/FormDesigner";

import { ChartList } from "./configuration";

import {
  editComponent,
  addComponent,
  getComponent,
} from "@/api/screenConfig/dataComponents";
import { fieldTypeColor } from "./common";
import CommonGraph from "./graph";
import { getReportsData } from "@/api/screenConfig/dataSet";
import { mapGetters } from "vuex";

export default {
  name: "config",
  components: {
    CommonGraph,
    BaseChart,
    IconButton,
    DataSetDialog,
    AnalysisDialog,
    ThemeDialog,
    RelationDialog,
    FieldConfigContainer,
    CommonDrawer,
    FormDesigner,
  },
  props: {
    departmentList: {
      type: Array,
      default: () => [],
    },
    type: {},
    classType: {},
    id: {
      type: String,
    },
    typeName: {
      type: String,
      default: "无",
    },
  },
  data() {
    return {
      isEdit: false, // 是否编辑
      isEditDialog: false, // 是否显示编辑弹框
      isOptionDrawer: false, // 图表配置项抽屉开关
      isRefresh: false, // 刷新频率框
      isPersistenceLoading: false, // 保存按钮状态
      isPageDataLoading: false,
      isChartType: false,
      searchField: "", // 搜索字段
      datasetName: "", // 数据集名称
      fieldHeight: 300, // 左边字段控制按钮位置
      allFieldList: [], // 所有字段列表
      chartTypeList: ChartList,
      currentHoverChartType: null, // 当前悬浮的图表类型
      currentHoverChartDataPoolConfig: [],

      dataPoolField: {}, // 生成图表配置项 所需 字段配置容器数据
      dataField: [], // 数据集实时获取的字段
      dataPoolList: [], // 生成图表配置项 所需 的数据 页面临时配置
      dataPoolTotal: 0,
      styleOptionConfig: [], // 生成图表配置项 所需 的图表样式配置
      themeStyle: {}, // 生成图表配置项 所需 全局主题样式
      relationConfig: {}, // 联动配置项(关联配置)

      refreshRateList: [
        { label: "不刷新", value: -1 },
        { label: "1分钟", value: 60 },
        { label: "2分钟", value: 120 },
        { label: "5分钟", value: 300 },
        { label: "10分钟", value: 600 },
        { label: "15分钟", value: 900 },
        { label: "30分钟", value: 1800 },
        { label: "1小时", value: 3600 },
      ],
      option: {},
      config: {
        isPaginationDisabled: true,
      },
      dragField: {
        status: false, // 是否显示
        source: "", // 事件来源 start 为左侧拖入 end 为顶部拖出
        fieldName: "",
        fieldType: "",
        fieldDescribe: "",
        left: 0,
        top: 0,
      }, // 拖拽元素配置项
      form: {
        id: "",
        name: "",
        description: "",
        type: "", // 分类ID
        datasetId: "", // 关联的数据集id
        chartType: "", // 图表类型
        classType: "", // 分类类别 报表组件/审计组件
        analysis: "", // 维度分析(内容为富文本,字段需要大一点)
        pageConfig: "{}", // 页面配置项
        refresh: -1, // 刷新频率
        chartConfig: "{}", // 图表配置项
        theme: "", // 主题
        deptId: null,
        relationComponentId: "", // 关联的组件id
      },
      lastChartType: "", // 上一次数据库保存的图表类型,仅用于判断是否需要主题
      rules: {
        name: [{ required: true, message: "请输入组件名称", trigger: "blur" }],
        // deptId: [{ required: true, message: '请选择组织', trigger: 'blur' }]
      },
      globalThemeColor: "", // 存放全局主题
    };
  },
  computed: {
    ...mapGetters(["systemInfo"]),
    // 维度字段列表
    dimensionList: function () {
      return this.fieldList.filter((item) => item.fieldType !== "number");
    },
    // 指标字段列表
    indicatorsList: function () {
      return this.fieldList.filter((item) => item.fieldType === "number");
    },
    // 获取所有已配置的字段列表
    allDataPoolFieldList: function () {
      return Object.keys(this.dataPoolField).reduce((r, c) => {
        let list = this.dataPoolField[c].reduce((lr, lc) => {
          lr.push({
            label: lc.fieldDescribe,
            value: lc.fieldName,
          });
          return lr;
        }, []);
        r.push(...list);
        return r;
      }, []);
    },
    // 用于监听字段位置变化
    dragPosition: function () {
      return this.dragField.left + this.dragField.top;
    },
    // 当前图表类型 生成所需的字段配置容器
    fieldContainerList: function () {
      // edit by 2021-12-15
      return this.currentDataPoolConfig.reduce((r, c) => {
        r.push({
          ...c,
          isHover: false,
          isPut: this.currentPutKey.includes(c.key),
        });
        return r;
      }, []);
    },
    // 当前选中的图表类型的相关信息
    currentChartType: function () {
      // edit by 2021-12-15
      return this.chartTypeList.find(
        (ct) => ct.getInfo().type === this.form.chartType
      );
    },
    // 当前拖拽的字段类型 根据 当前选中的图表类型 确定 能被那个容器放置
    currentPutKey: function () {
      // edit by 2021-12-15
      return this.currentDataPoolConfig.reduce((r, c) => {
        if (
          this.dragField.fieldType &&
          c.type.includes(this.dragField.fieldType)
        ) {
          r.push(c.key);
        }
        return r;
      }, []);
    },
    currentGraph: function () {
      return this.currentChartType
        ? this.currentChartType.getInfo().component
        : null;
    },
    currentDataPoolConfig: function () {
      return this.currentChartType
        ? this.currentChartType.getDataPoolConfig()
        : [];
    },
    // 左侧筛选后的字段列表
    fieldList: function () {
      return this.allFieldList.reduce((r, c) => {
        if (
          c.fieldName.includes(this.searchField) ||
          c.fieldDescribe.includes(this.searchField)
        ) {
          r.push(c);
        }
        return r;
      }, []);
    },
    // 当前已经配置的字段数量 用于监听字段配置变化
    currentConfigFieldLength: function () {
      return Object.keys(this.dataPoolField).reduce((r, c) => {
        if (this.dataPoolField[c] instanceof Array) {
          r = r + this.dataPoolField[c].length;
        }
        return r;
      }, 0);
    },
    refreshLabel: function () {
      let refresh = this.refreshRateList.find(
        (rr) => rr.value === this.form.refresh
      );
      return refresh?.label || "不刷新";
    },
  },
  watch: {
    dragPosition: function () {
      this.fieldListener();
    },
    currentChartType: function () {
      if (this.currentChartType) {
        this.dataPoolField = this.currentDataPoolConfig.reduce((r, c) => {
          r[c.key] = [];
          return r;
        }, {});

        this.mergeThemeConfig();
      }
    },
    currentConfigFieldLength: function () {
      this.setOption();
    },
  },
  methods: {
    getCheckedDeptId(val) {
      this.form.deptId = val;
    },
    initPageData() {
      // 默认选中第一个图表类型
      this.form.chartType = this.chartTypeList[0].getInfo().type;

      this.form.type = this.$route.query.type;
      if (!this.form.datasetId) this.chooseDataSet();
    },
    mergeThemeConfig() {
      const styleOptionConfig = this.currentChartType.getStyleOptionConfig();

      if (this.lastChartType) {
        if (this.currentChartType.getInfo().type === this.lastChartType) {
          // 当前图表为数据库存储的图表 不需要加载主题
        } else {
          // 加载主题颜色
          this.form.theme = this.globalThemeColor;

          // 加载全局主题配置
          const themeStyleConfig = this.currentChartType._transformStyleOption(
            this.themeStyle
          );
          this.styleOptionConfig =
            this.currentChartType._mergeStyleOptionConfig(
              styleOptionConfig,
              themeStyleConfig
            );
        }
      } else {
        // 加载主题颜色
        this.form.theme = this.globalThemeColor;

        this.styleOptionConfig = styleOptionConfig;
      }
    },
    clearPageStatus(e) {
      this.isOptionDrawer = false;
    },
    chooseDataSet() {
      this.$refs.dataset.show();
    },
    handleAnalysis() {
      this.$refs.analysis.show();
    },
    handleTheme() {
      this.$refs.theme.show();
    },
    handleRelation() {
      this.$refs.relation.show();
    },

    /**
     * 清除事件
     */
    clearEvent() {
      document.onmousemove = undefined;
      document.onmouseup = undefined;
      this.resetDragField();
    },
    /**
     *左侧字段高度控制按钮 鼠标按下事件
     * @param e 事件对象
     */
    dragMousedown(e) {
      // minPosition 最小保留距离
      // currentHeight 当前按钮位置备份
      // pageY 当前鼠标点击时鼠标距离屏幕上面的距离
      const minPosition = 100,
        currentHeight = this.fieldHeight,
        pageY = e.pageY;
      // 外层容器高度
      const { height: containerHeight } =
        this.$refs.fieldContainer.getBoundingClientRect();

      // 鼠标移动事件
      document.onmousemove = (event) => {
        let position = event.pageY - pageY;

        // 如果鼠标上下移动距离 加上 当前位置 在 范围里面 则 可以移动
        if (
          currentHeight + position < containerHeight - minPosition &&
          currentHeight + position > minPosition
        ) {
          this.fieldHeight = currentHeight + position;
        }
      };

      // 全局鼠标松开方法
      document.onmouseup = (event) => {
        this.clearEvent();
      };
    },
    /**
     *左侧字段高度控制按钮 鼠标松开事件
     */
    dragMouseup() {
      this.clearEvent();
    },
    resetDragField() {
      this.setDragFieldStatus();
      this.setDragFieldSource();
      this.setDragFieldInfo();
      this.setDragFieldPosition();
    },
    setDragFieldInfo(fieldName = "", fieldType = "", fieldDescribe = "") {
      this.dragField.fieldName = fieldName;
      this.dragField.fieldType = fieldType;
      this.dragField.fieldDescribe = fieldDescribe;
    },
    setDragFieldPosition(left = 0, top = 0) {
      this.dragField.left = left;
      this.dragField.top = top;
    },
    setDragFieldStatus(status = false) {
      this.dragField.status = status;
    },
    setDragFieldSource(source = "") {
      this.dragField.source = source;
    },
    /**
     *
     * @param e 事件对象
     * @param field 字段对象
     * @param source
     */
    fieldMousedown(e, field, source) {
      let { fieldName, fieldType, fieldDescribe } = field;
      this.setDragFieldSource(source);
      this.setDragFieldInfo(fieldName, fieldType, fieldDescribe);
      this.setDragFieldPosition(e.pageX, e.pageY);
      this.setDragFieldStatus(true);

      document.onmousemove = ({ pageX, pageY }) => {
        this.setDragFieldPosition(pageX, pageY);
      };

      // 全局鼠标松开方法
      document.onmouseup = () => {
        // console.log('在页面上松开')
        this.handleDragField();
        this.clearEvent();
      };
    },
    fieldMouseup() {
      console.log("在左侧点击字段上松开");
    },
    dragFieldMouseup() {
      // console.log('在拖拽节点上松开')
      this.handleDragField();
      this.clearEvent();
    },
    deleteConfigField(containerKey, field) {
      this.deleteDataPoolField(containerKey, field);
    },
    /**
     * 字段位置监听方法
     * 中间处理者
     */
    fieldListener() {
      // edit by 2021-12-15
      if (this.currentChartType) {
        this.currentDataPoolConfig.forEach((dc) => {
          let { key } = dc;
          let elements = this.$refs[key],
            currentContainer = this.fieldContainerList.find(
              (c) => c.key === key
            );
          if (elements && elements instanceof Array && elements.length) {
            let { left, top, width, height } =
              elements[0].getBoundingClientRect();
            currentContainer.isHover =
              this.dragField.left > left &&
              this.dragField.top > top &&
              this.dragField.left < left + width &&
              this.dragField.top < top + height;
          }
        });
      } else {
        console.log("找不到字段配置框! [原因] [未选择图表类型]");
      }
    },
    /**
     * 处理拖拽节点 鼠标松开事件
     */
    handleDragField() {
      // edit by 2021-12-15
      let field = this.allFieldList.find(
        (field) => field.fieldName === this.dragField.fieldName
      );
      let dataPoolConfig = this.currentDataPoolConfig;
      if (field && dataPoolConfig) {
        dataPoolConfig.forEach((dc) => {
          let { key } = dc;
          // 当前字段支持的容器key
          this.fieldContainerList.forEach((container) => {
            // 当前容器
            if (container.key === key) {
              // 当前节点是否在容器内
              if (container.isHover && container.isPut) {
                // 在容器内
                // 放置
                this.addConfigField(key, field);
              } else {
                // 不在容器内
                // 删除
                this.delConfigField(key, field);
              }
            } else {
              // 不是当前容器
            }
          });
        });
      } else {
        console.warn("当前拖拽节点丢失,请排查问题");
      }
    },
    /**
     * 添加字段
     * @param key 容器key
     * @param field 当前拖拽字段
     */
    addConfigField(key, field) {
      if (this.dragField.source === "start") {
        let dataPoolConfig = this.currentDataPoolConfig;
        let config = dataPoolConfig.find((dc) => dc.key === key);
        if (!this.dataPoolField[key]) this.dataPoolField[key] = [];
        if (config) {
          if (config.limit === -1) {
            // -1 无限制
            let index = this.dataPoolField[key].findIndex(
              (cf) => cf.key === field.key
            );
            if (index === -1) this.dataPoolField[key].push(field);
          } else if (config.limit > 0) {
            // 有限制
            if (this.dataPoolField[key].length < config.limit) {
              // 限制数量内允许添加
              let index = this.dataPoolField[key].findIndex(
                (cf) => cf.key === field.key
              );
              if (index === -1) this.dataPoolField[key].push(field);
            } else {
              // 超出限制
              this.$GlobalErrorMessage(`数量限制: ${config.limit}个`);
            }
          } else {
            // 为 0 不可添加
          }
        } else {
          // 需要放置的 在原始数据里面未找到对应数据
        }
      } else {
        // 配置框拖拽不触发
      }
    },
    /**
     * 删除字段
     * @param key 容器key
     * @param field 当前拖拽字段
     */
    delConfigField(key, field) {
      if (this.dragField.source === "end") {
        this.deleteDataPoolField(key, field);
      } else {
        // 字段框拖拽不触发
      }
    },

    /**
     * 删除配置狂里面的字段
     */
    deleteDataPoolField(key, field) {
      let index = this.dataPoolField[key].findIndex(
        (cf) => cf.key === field.key
      );
      if (index !== -1) {
        console.log("将要被删除字段: ", field.fieldName);

        this.checkPoolFieldIsUse(field.fieldName)
          .then(() => {
            this.dataPoolField[key].splice(index, 1);
          })
          .catch(() => {
            console.log("用户取消删除");
          });
      }
    },

    checkPoolFieldIsUse(poolField) {
      return new Promise((resolve, reject) => {
        let { triggerField } = this.relationConfig;
        if (poolField === triggerField) {
          this.$GlobalDeleteConfirm(
            "该字段已被组件关联，删除后将无法正常加载关联组件！是否继续删除？"
          )
            .then(() => {
              resolve();
            })
            .catch(() => {
              reject();
            });
        } else {
          resolve();
        }
      });
    },

    chartTypeChange(ct) {
      this.form.chartType = ct.getInfo().type;
      this.isChartType = false;
      this.lastChartType = ""; // 切换图表类型后重置 缓存数据
    },
    chartTypeMouseover(chartType) {
      this.currentHoverChartType = this.chartTypeList.find(
        (ct) => ct.getInfo().type === chartType.getInfo().type
      );
      this.currentHoverChartDataPoolConfig = this.currentHoverChartType
        ? this.currentHoverChartType.getDataPoolConfig()
        : [];
    },
    chartTypeMouseleave(ct) {
      this.currentHoverChartType = null;
      this.currentHoverChartDataPoolConfig = [];
    },
    datasetChange(dataset) {
      // 数据源改变后清除字段配置
      this.resetConfig();

      let { id, name, list, field, total } = dataset;
      this.allFieldList = field;
      this.dataField = field;
      this.dataPoolList = list;
      this.dataPoolTotal = total;
      this.datasetName = name;
      this.form.datasetId = id;
    },
    resetConfig() {
      Object.keys(this.dataPoolField).forEach(
        (key) => (this.dataPoolField[key] = [])
      );
    },
    analysisChange(v) {
      this.form.analysis = v;
    },
    themeChange(v) {
      this.form.theme = v;
      this.setOption();
    },
    relationChange(v) {
      console.log("关联组件配置: ", v);
      this.relationConfig = v;
      if (v?.componentId) this.form.relationComponentId = v.componentId;
    },
    showOptionDrawer() {
      this.isOptionDrawer = true;
    },
    styleOptionConfigChange(styleOptionConfig) {
      this.styleOptionConfig = styleOptionConfig;
      this.setOption();
    },
    setOption() {
      this.option = this.currentChartType.getOption({
        dataField: this.dataField,
        dataList: this.dataPoolList,
        dataTotal: this.dataPoolTotal,
        dataPoolField: this.dataPoolField,
        styleOptionConfig: this.styleOptionConfig,
        themeColor: this.form.theme.split(","),
        themeStyle: this.themeStyle,
      });
    },
    refreshRateChange(item) {
      this.form.refresh = item.value;
      this.isRefresh = false;
    },

    back() {
      this.$emit("close");
    },

    handleEditDialog() {
      this.isEditDialog = true;
    },

    /**
     * 获取主题配置
     * 1. 新增页面需要合并主题
     * 2. 编辑页面首次不需要合并主题,修改过图表类型需要
     * 3.
     */
    getThemeList() {
      this.$refs.theme
        .commonGetThemeData()
        .then((theme) => {
          let { colors, themeOption } = theme;
          this.globalThemeColor = colors;

          let option = {};

          try {
            option = JSON.parse(themeOption);
          } catch (e) {
            console.warn("主题配置项转换异常: ", e);
            console.warn("主题配置: ", themeOption);
          }
          this.themeStyle = {
            option,
          };
        })
        .finally(() => {
          this.mergeThemeConfig();
        });
    },

    persistence() {
      if (!this.form.datasetId) {
        this.$GlobalErrorConfirm("保存失败", "请选择数据集");
        return;
      }

      let count = Object.keys(this.dataPoolField).reduce((r, c) => {
        if (
          this.dataPoolField[c] &&
          this.dataPoolField[c] instanceof Array &&
          this.dataPoolField[c].length > 0
        ) {
        } else {
          r += 1;
        }
        return r;
      }, 0);

      if (count > 0) {
        this.$GlobalErrorConfirm("保存失败", "请配置字段");
        return;
      }

      let pageConfig = {
        dataPoolField: this.dataPoolField,
        relationConfig: this.relationConfig,
      };

      let chartConfig = {
        styleOption: this.currentChartType._transformStyleOptionConfig(
          this.styleOptionConfig
        ),
      };

      let params = {
        ...this.form,
        type: this.type,
        classType: this.classType,
        pageConfig: JSON.stringify(pageConfig),
        chartConfig: JSON.stringify(chartConfig),
      };

      console.log("params: ", params);

      if (!this.form.name)
        return this.$GlobalErrorConfirm(
          this.isEdit ? "编辑失败" : "新增失败",
          "请输入组件名称"
        );

      this.isPersistenceLoading = true;
      if (this.isEdit) {
        editComponent(params)
          .then((res) => {
            if (res && res.code === 200) {
              this.$GlobalSuccessMessage("编辑成功");
              this.back();
            } else {
              this.$GlobalErrorConfirm("编辑失败", res.msg);
            }
          })
          .finally(() => {
            this.isPersistenceLoading = false;
          });
      } else {
        addComponent(params)
          .then((res) => {
            if (res && res.code === 200) {
              this.$GlobalSuccessMessage("新增成功");
              this.back();
            } else {
              this.$GlobalErrorConfirm("新增失败", res.msg);
            }
          })
          .finally(() => {
            this.isPersistenceLoading = false;
          });
      }
    },

    getComponent() {
      this.isPageDataLoading = true;
      getComponent({ id: this.form.id }).then((res) => {
        if (res && res.code == 200) {
          let component = res.data;

          this.form.id = component.id;
          this.form.name = component.name;
          this.form.analysis = component.analysis;
          this.form.chartType = component.chartType;
          this.lastChartType = component.chartType; // 临时存储
          this.form.datasetId = component.datasetId;
          this.form.description = component.description;
          this.form.refresh = component.refresh;
          this.form.theme = component.theme || "";
          this.form.type = component.type;
          this.form.deptId = component.deptId;

          try {
            let { relationConfig } = JSON.parse(component.pageConfig);
            this.relationConfig = relationConfig ?? {};
          } catch (e) {
            this.relationConfig = {};
            console.error("绑定关系转换异常: ", e);
          }

          this.$refs.dataset
            .getDataSetById(component.dataset.id)
            .then((res) => {
              let { datasetData, datasetField, datasetTotal } = res;

              this.datasetChange({
                list: datasetData,
                field: datasetField,
                total: datasetTotal,
                id: component.dataset.id,
                name: component.dataset.name,
              });
            })
            .finally(() => {
              this.isPageDataLoading = false;
              try {
                let { styleOption } = JSON.parse(component.chartConfig);

                const defaultStyleOptionConfig =
                  this.currentChartType.getStyleOptionConfig(); // 图表默认配置项
                const commonStyleOptionConfig =
                  this.currentChartType._transformStyleOption(styleOption); // 数据库保存的配置项
                this.styleOptionConfig =
                  this.currentChartType._mergeStyleOptionConfig(
                    defaultStyleOptionConfig,
                    commonStyleOptionConfig
                  );
              } catch (e) {}

              try {
                let { dataPoolField } = JSON.parse(component.pageConfig);
                this.currentChartType._updateDataPoolField(
                  this.dataField,
                  dataPoolField
                );
                this.dataPoolField = Object.assign(
                  this.dataPoolField,
                  dataPoolField
                );
              } catch (e) {
                console.log("e: ", e);
              }
            });
        } else {
        }
      });
    },

    variableChange(variable) {
      this.updateComponentData(variable);
    },

    updateComponentData(variableConfig) {
      getReportsData({
        datasetId: this.form.datasetId,
        dataSetVariableConfig: variableConfig,
      })
        .then((res) => {
          if (res && res.code === 200) {
            let { dataList, dataField, total } = res.data;
            this.dataField = dataField;
            this.dataPoolList = dataList;
            this.dataPoolTotal = total;
          } else {
            this.dataField = [];
            this.dataPoolList = [];
            this.dataPoolTotal = 0;
          }
        })
        .finally(() => {
          this.setOption();
        });
    },
  },
  mounted() {
    this.getThemeList();

    if (this.id) {
      // console.log('组件编辑')
      // 编辑
      this.form.id = this.id;
      this.isEdit = true;
      this.getComponent();
    } else {
      // console.log('组件新增')
      // 新增
      this.isEdit = false;
      this.initPageData();
    }
  },
};
</script>

<style scoped lang="scss">
.screen-container {
  width: 100%;
  height: 100%;
  display: flex;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;

  .common-field-container {
    width: 120px;
    height: 20px;
    line-height: 20px;
    text-align: center;
    font-size: 12px;
    color: #303133;
    border-radius: 8px 0 8px 0;
    cursor: pointer;
    flex: 0 0 auto;
    position: relative;
  }

  .drag-field {
    position: fixed;
    z-index: 99;
    transform: translate(-50%, -50%);

    .drag-field-inside {
      width: calc(100% - 40px);
      height: 100%;
      margin: 0 20px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }

  .config-field {
    margin: 0 4px;

    &:hover {
      .config-field-inside {
        .el-icon-delete {
          opacity: 1;
        }
      }
    }

    .config-field-inside {
      width: calc(100% - 40px);
      height: 100%;
      margin: 0 20px;
      //background-color: red;

      .el-icon-delete {
        width: 12px;
        height: 12px;
        line-height: 12px;
        font-size: 12px;
        position: absolute;
        right: 5px;
        top: calc(50% - 6px);
        color: #f56c6c;
        //color: #fff;
        opacity: 0;
        transition: opacity 0.15s linear;
      }
    }
  }

  .type-string {
    background-color: #c6d2ec;
  }

  .type-number {
    background-color: #b9e0dd;
  }

  .type-date {
    background-color: orange;
  }

  .left-config-wrap {
    width: 199px;
    height: 100%;
    padding: 12px;
    box-sizing: border-box;
    border-right: 1px solid #eee;

    .data-set-wrap {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;

      .title {
        color: #000;
        font-size: 16px;
        font-weight: bold;
        width: calc(100% - 20px);
        margin-right: 4px;
      }

      .tool {
        width: 16px;
        height: 16px;
        color: var(--theme-color);
        cursor: pointer;

        svg {
          width: 16px;
          height: 16px;
        }
      }
    }

    .field-list-wrap {
      width: 100%;
      height: calc(100% - 22px - 32px);
      user-select: none;

      .field-group-list-wrap {
        width: 100%;
        padding-top: 12px;
        box-sizing: border-box;
        overflow-y: scroll;

        .field-group-title {
          font-size: 14px;
          color: #000;
          font-weight: bold;
        }

        .field-list {
          .field-item-wrap {
            height: 28px;
            font-size: 14px;
            box-sizing: border-box;
            color: #303133;
            cursor: pointer;
            display: flex;
            align-items: center;
            padding-left: 8px;

            &:hover {
              background-color: #efefef;
            }

            svg {
              width: 14px;
              height: 14px;
              margin-right: 4px;
            }
          }
        }
      }

      .field-control {
        width: 100%;
        height: 15px;
        display: flex;
        justify-content: center;
        align-items: center;
        border-bottom: 1px solid #eee;

        .control-button {
          width: 20px;
          height: 100%;
          line-height: 1;
          text-align: center;
          cursor: ns-resize;
          color: #606266;
        }
      }
    }
  }

  .right-config-wrap {
    height: 100%;
    width: calc(100% - 200px);
    display: flex;
    flex-direction: column;

    .field-config-container-wrap {
      display: flex;
      flex-wrap: wrap;

      .field-config-container {
        width: 100%;
        height: 39px;
        border-bottom: 1px solid #eee;
        display: flex;
        align-items: center;
        flex: 0 1 auto;

        .config-title {
          width: 99px;
          height: 30%;
          display: flex;
          justify-content: center;
          align-items: center;
          color: #303133;
          font-size: 14px;
          border-right: 1px solid #acacac;
        }

        .field-content {
          width: calc(100% - 98px - 8px);
          height: 30px;
          border-width: 1px;
          border-style: dashed;
          border-color: transparent;
          margin: 0 4px;
          display: flex;
          justify-content: flex-start;
          align-items: center;

          .field-description {
            color: #909399;
            font-size: 14px;
            white-space: nowrap;
            padding-left: 12px;
          }
        }
      }
    }

    .tools-control-wrap {
      width: 100%;
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      flex: 0 1 auto;
    }

    .chart-preview-wrap {
      width: 100%;
      position: relative;
      flex: 1 1 auto;
      overflow: hidden;

      .chart-preview-container {
        width: 100%;
        height: 100%;
        padding: 18px;
        box-sizing: border-box;
      }
    }
  }
}
</style>

<style lang="scss">
.chart-type-list-popover {
  padding: 4px;

  .chart-type-list-container {
    box-sizing: border-box;

    .chart-group-title {
      padding: 2px;
      box-sizing: border-box;
      font-size: 12px;
      font-weight: bold;
    }

    .chart-type-list-wrap {
      width: 140px;
      display: flex;
      flex-wrap: wrap;
      margin-bottom: 8px;

      .chart-type-item-wrap {
        width: 24px;
        height: 24px;
        border-width: 2px;
        border-style: solid;
        border-color: transparent;

        display: flex;
        justify-content: center;
        align-items: center;
        margin: 2px;
        cursor: pointer;

        &:hover {
          border-color: var(--theme-color);
        }

        svg {
          width: 14px;
          height: 14px;
        }
      }

      .checked {
        border-color: var(--theme-color) !important;
      }
    }

    .chart-field-info {
      font-size: 12px;
      white-space: nowrap;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      padding-left: 4px;

      .tag {
        width: 30px;
        color: var(--theme-color);
      }
    }
  }
}

.refresh-rate-wrap {
  padding: 4px;
  box-sizing: border-box;

  .refresh-rate-item {
    height: 24px;
    padding: 0 4px;
    font-size: 12px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    cursor: pointer;

    &:hover {
      background-color: #eee;
    }
  }
}

.header-edit-name {
  display: flex;
  align-items: center;

  .line {
    color: #303133;
    margin-right: 18px;
  }

  .label {
    width: 100px;
    color: #303133;
    font-size: 15px;
  }
}
</style>
